<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .sullivan-grid-3x3 {
            margin-left: 100px;
            margin-top: 100px;
            width: 600px;
            height: 600px;
            border: 1px solid red;
            display: grid;
            gap: 6px;
            .sullivan-grid-item {
                position: relative;
                border: 1px solid blue;
            }
        }
        .sullivan-grid-item-header {
            grid-area: header;
        }
        .sullivan-grid-item-direction {
            background: rgba(0, 0, 0, .3)
        }
        .sullivan-grid-item-top,
        .sullivan-grid-item-bottom {
            position: absolute;
            height: 10px;
            width: 100%;
            cursor: row-resize;
        }
        .sullivan-grid-item-right,
        .sullivan-grid-item-left {
            position: absolute;
            width: 10px;
            height: 100%;
            cursor: col-resize;
        }
        .sullivan-grid-item-top {
            top: -3px;
        }
        .sullivan-grid-item-right {
            right: -3px;
        }
        .sullivan-grid-item-bottom {
            bottom: -3px;
        }
        .sullivan-grid-item-left {
            left: -3px;
        }
    </style>
</head>
<body>
<div id="container"></div>
<script src="./jquery.js"></script>
<script>
    function createGrid(grid = [1, 1], gap = [6, 6]) {
        if (grid.length < 2) return;
        const [row, col] = grid;
        const [rowGap, columnGap] = gap;
        const className = `sullivan-grid sullivan-grid-${grid.join("x")}`;
        const rowStyle = `repeat(${row}, 1fr)`;
        const colStyle = `repeat(${col}, 1fr)`;
        const $grid = $(`<div class="${className}" style="display: grid;" ></div>`);

        $grid.css({
            "grid-template-rows": rowStyle,
            "grid-template-columns": colStyle,
            "grid-row-gap": rowGap,
            "grid-column-gap": columnGap,
        });

        const areas = new Array(row).fill("")
        const createDirection = (direction) => (
            `<div class="sullivan-grid-item-direction sullivan-grid-item-${direction}"></div>`
        );

        for (let i = 0; i < row; i++) {
            for (let j = 0; j < col; j++) {
                const $gridItem = $(
                    `<div class="sullivan-grid-item" data-index="${i + 1}" style="grid-area: grid-gap-${i}x${j}"></div>`
                );

                $gridItem.append(['top', 'right', 'bottom', 'left'].map(createDirection))
                areas[i] += `grid-gap-${i}x${j} `
                $grid.append($gridItem);
            }

            areas[i] = areas[i].trim();
        }

        $grid.css({
            "grid-template-areas": `"${areas.join('" "')}"`
        });
        return $grid;
    }

    const $grid = createGrid([3, 3])
    const $container = $('#container');

    $container.html($grid)

    class Coordinate {
        x = 0;
        y = 0;

        constructor(x, y) {
            this.x = x;
            this.y = y;
        }

        update (x, y) {
            this.x = x;
            this.y = y;
        }
    }

    class Size {
        top;
        right;
        bottom;
        left;
        width;
        height;
        constructor($item) {
            this.update($item)
        }
        update = ($item) => {
            const { top, left } = $item.offset()
            this.width = $item.width();
            this.height = $item.height();
            this.top = top;
            this.right = left + this.width;
            this.bottom = top + this.height;
            this.left = left;
        }
    }

    function updateView (type, move, size) {
        switch (type) {
            case 'top': {
                if (move.y > 20) {

                }
                break
            }
            case 'right': {
                break
            }
            case 'bottom': {
                break
            }
            case 'left': {
                break
            }
        }
    }

    class Position {
        type;
        activated;
        playground;
        size;
        start;
        end;
        move;

        constructor(type) {
            this.activated = new Set();
            this.type = type;
        }

        setStart(event) {
            const index = $(event.target).closest('.sullivan-grid-item').index();
            // 设置当前操作覆盖的区域
            this.activated.add(index);
            // 开始位置
            this.start = new Coordinate(event.screenX, event.screenY);
            // 移动距离
            this.move = new Coordinate(0, 0);
            // 大小
            this.size = new Size($(event.target).closest('.sullivan-grid-item'));
            // 背景板
            this.playground = new Size($(event.target).closest('.sullivan-grid'));
            console.log('start: => ', event);
        }

        setMove(event) {
            const { left, right, top, bottom } = this.playground
            if (event.screenX >= left && event.screenX <= right && event.screenY >= top && event.screenY <= bottom) {
                this.move.update(event.screenX - this.start.x, event.screenY - this.start.y);

            }
            console.log('move: => ', this, this.move, event)
        }

        setEnd(event) {
            this.end = new Coordinate(event.screenX, event.screenY);
            this.move.update(event.screenX - this.start.x, event.screenY - this.start.y);
            console.log('end: => ', this.end)
        }
    }

    let position;


    const cursor = {
        set (cursor) {
            $(document.body).css('cursor', cursor + '-resize')
        },
        remove () {
            $(document.body).css('cursor', 'initial')
        }
    }

    function onTopMouseDown (event) {
        event.stopPropagation()
        cursor.set('row')
        position = new Position('top')
        position.setStart(event)
        bindMouseMove()
    }
    function onRightMouseDown (event) {
        event.stopPropagation()
        cursor.set('column')
        position = new Position('right')
        position.setStart(event)
        bindMouseMove()
    }
    function onBottomMouseDown (event) {
        event.stopPropagation()
        cursor.set('row')
        position = new Position('bottom')
        position.setStart(event)
        bindMouseMove()
    }

    function onLeftMouseDown (event) {
        event.stopPropagation()
        cursor.set('column')
        position = new Position('left')
        position.setStart(event)
        bindMouseMove()
    }

    function bindMouseMove () {
        $(document)
            .off('mousemove', onMouseMove)
            .on('mousemove', onMouseMove)
    }

    function offMouseMove () {
        console.log('offMouseMove')
        cursor.remove()
        $(document).off('mousemove', onMouseMove)
    }

    function onMouseMove (event) {
        console.log('onMouseMove')
        if (event.which) {
            position.setMove(event)
        } else {
            offMouseMove()
        }
    }

    function onMouseUp (event) {
        offMouseMove()
    }

    function onMouseOut (event) {
        if (position) {
            console.log(event.screenX, position.playground.left)
            if (event.screenX < position.playground.left) {
                offMouseMove()
            }
        }
    }

    $container.on('mousedown', '.sullivan-grid-item-top', onTopMouseDown)
    $container.on('mousedown', '.sullivan-grid-item-right', onRightMouseDown)
    $container.on('mousedown', '.sullivan-grid-item-bottom', onBottomMouseDown)
    $container.on('mousedown', '.sullivan-grid-item-left', onLeftMouseDown)
    // $container.on('mouseout', onMouseOut)
    $(document).on('mouseup', onMouseUp)

</script>
</body>
</html>